from fastapi import APIRouter, Depends, Security
from fastapi.responses import JSONResponse
from typing import List

from myProfile.models.data.myProfile_models import Signup, Login
from myProfile.repository.signup import SignupRepository
from myProfile.models.request.myProfile_request import SignupReq
from myProfile.db_config.odmantic_config import create_db_engine
from myProfile.security.secure import get_current_valid_user

from datetime import date, datetime
from json import dumps, loads

router = APIRouter()


def json_serial(obj):
    if isinstance(obj, (datetime, date)):
        return obj.strftime('%Y-%m-%dT%H:%M:%S.%f')
    raise TypeError("The type %s not serializable." % type(obj))


@router.post("/signup/add")
async def add_signup(req: SignupReq, engine=Depends(create_db_engine)):
    signup_dict = req.model_dump(exclude_unset=True)
    signup_json = dumps(signup_dict, default=json_serial)
    repo: SignupRepository = SignupRepository(engine)
    user: Signup = await repo.get_signup_username(req.username)
    if user is not None:
        return JSONResponse(
            content={"message": f"username {req.username} already exists."},
            status_code=403)

    result = await repo.insert_signup(loads(signup_json))
    if result is True:
        return req
    else:
        return JSONResponse(
            content={"message": "create signup problem encountered."},
            status_code=500)


@router.patch("/signup/update/{id}")
async def update_signup(id: int, req: SignupReq,
                        current_user: Login = Security(
                            get_current_valid_user, scopes=["admin_write"]),
                        engine=Depends(create_db_engine)):
    signup_dict = req.model_dump(exclude_unset=True)
    signup_json = dumps(signup_dict, default=json_serial)
    repo: SignupRepository = SignupRepository(engine)
    result = await repo.update_signup(id, loads(signup_json))
    if result is True:
        return req
    else:
        return JSONResponse(
            content={"message": "update signup unsuccessfully"},
            status_code=500)


@router.delete("/signup/delete/{id}")
async def delete_signup(id: int,
                        current_user: Login = Security(
                            get_current_valid_user, scopes=["admin_write"]),
                        engine=Depends(create_db_engine)):
    repo: SignupRepository = SignupRepository(engine)
    result = await repo.delete_signup(id)
    if result is True:
        return JSONResponse(
            content={"message": "delete signup successfully"},
            status_code=201)
    else:
        return JSONResponse(
            content={"message": "delete signup unsuccessfully"},
            status_code=500)


@router.get("/signup/get/all", response_model=List[SignupReq])
async def get_all_signup(current_user: Login = Security(
                            get_current_valid_user, scopes=["admin_read"]),
                         engine=Depends(create_db_engine)):
    repo: SignupRepository = SignupRepository(engine)
    return await repo.get_all_signup()


@router.get("/signup/get/username")
async def get_signup_username(username: str,
                              current_user: Login =
                              Security(get_current_valid_user,
                                       scopes=["admin_read"]),
                              engine=Depends(create_db_engine)):
    repo: SignupRepository = SignupRepository(engine)
    return await repo.get_signup_username(username)


@router.get("/signup/get/{id}", response_model=SignupReq)
async def get_signup_id(id: int,
                        current_user: Login = Security(
                            get_current_valid_user, scopes=["admin_read"]),
                        engine=Depends(create_db_engine)):
    repo: SignupRepository = SignupRepository(engine)
    return await repo.get_signup(id)
